﻿using Dos.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace FaceIdentifier
{
    public class FaceRepositoryManage
    {
        private readonly log4net.ILog _log = log4net.LogManager.GetLogger(typeof(FaceRepositoryManage));

        private readonly FaceApi _arcFaceApi;
        private readonly ServiceConfig _config = new ServiceConfig();
        private bool _runAsyn = false;
        private Encoding encoding = Encoding.GetEncoding("UTF-8");
        private string Repository = "人脸库";
        private string deviceSn = "";

        public FaceRepositoryManage(FaceApi faces)
        {
            _arcFaceApi = faces;
        }

        public void StartService()
        {
            if (_runAsyn)
            {
                return;
            }

            _runAsyn = true;
            _log.InfoFormat("准备启动人脸识别服务器同步");
            if (string.IsNullOrWhiteSpace(_config.Url()))
            {
                _log.Warn("未启用人脸服务器设置");
                return;
            }

            Task.Factory.StartNew(() =>
            {
                deviceSn = GetMacAddressByNetworkInformation();
                Thread.Sleep(5000);
                while (_runAsyn)
                {
                    try
                    {
                        FaceTimer_Elapsed();
                    }
                    catch (Exception ex)
                    {
                        _log.Error("权限同步异常", ex);
                    }
                    finally
                    {
                        Task.Delay(10000).Wait();
                    }
                }
            });
        }

        public void StopService()
        {
            _runAsyn = false;
        }

        private void FaceTimer_Elapsed()
        {
            _log.Debug("检查服务器权限同步 url:" + _config.Url());
            using (var client = new WebClient())
            {
                client.Encoding = encoding;
                var priList = new List<PrivilegeInfo>();
                try
                {
                    GetPrivilegeList(deviceSn, client, priList);

                }
                catch (Exception ex)
                {
                    _log.Error("请求服务器同步权限异常", ex);
                    return;
                }
                foreach (var item in priList)
                {
                    var destFileName = Repository + "/" + item.personSN + "_" + item.personName + ".jpg";
                    if ("delete".Equals(item.type))
                    {
                        RemoveFace(deviceSn, client, item, destFileName);
                    }
                    else
                    {
                        InsertFace(deviceSn, client, item, destFileName);
                    }
                    Thread.Sleep(1000);
                }

                if(priList.Count == 0)
                {
                    UploadFaceRecord(deviceSn, client);
                }
            }

        }

        private void GetPrivilegeList(string deviceSn, WebClient client, List<PrivilegeInfo> priList)
        {
            var priListJson = client.DownloadString(_config.Url() + "/face/getPrivilege?deviceSN=" + deviceSn);
            _log.Debug("服务器返回:" + priListJson);

            JObject googleSearch = JObject.Parse(priListJson);
            if (googleSearch["code"].Value<int>() == 0)
            {
                var results = googleSearch["msg"];
                foreach (var token in results)
                {
                    PrivilegeInfo info = token.ToObject<PrivilegeInfo>();
                    priList.Add(info);
                }
            }
        }

        private void InsertFace(string deviceSn, WebClient client, PrivilegeInfo item, string destFileName)
        {
            try
            {
                client.DownloadFile(_config.Url() + "/face/getFaceImage?deviceSN=" + deviceSn + "&personSN=" + item.personSN, "download.jpg");
                FileInfo fi = new FileInfo("download.jpg");
                if(fi.Length == 0)
                {
                    fi.Delete();
                    return;
                }

                using(Bitmap bitmap = new Bitmap("download.jpg"))
                {
                    _arcFaceApi.Add(item.personSN, bitmap);
                    File.Copy("download.jpg", destFileName);
                }
                var updateJson = client.DownloadString(_config.Url() + "/face/updatePrivilege?deviceSN=" + deviceSn + "&id=" + item.id + "&type=" + item.type);
                _log.Info("更新权限:" + updateJson);
            }
            catch (Exception ex)
            {
                _log.Error("更新权限异常", ex);
            }
        }

        private void RemoveFace(string deviceSn, WebClient client, PrivilegeInfo item, string destFileName)
        {
            try
            {
                _arcFaceApi.Remove(item.personSN);
                if(File.Exists(destFileName)){
                    File.Delete(destFileName);
                }
                var updateJson = client.DownloadString(_config.Url() + "/face/updatePrivilege?deviceSN=" + deviceSn + "&id=" + item.id + "&type=" + item.type);
                _log.Info("更新权限:" + updateJson);
            }
            catch (Exception ex)
            {
                _log.Error("删除权限异常", ex);
            }
        }

        private void UploadFaceRecord(string deviceSn, WebClient client)
        {
            try
            {

                string[] files = Directory.GetFiles("识别记录");
                for (int i = 0; i < Math.Min(10, files.Length); i++)
                {
                    _log.InfoFormat("准备上传识别记录:{0}", files[i]);
                    try
                    {
                        var fi = new FileInfo(files[i]);
                        var name = fi.Name.Replace(fi.Extension, "");
                        var splits = name.Split('_');
                        var personSn = splits[0];
                        var personName = splits[1];
                        var createTime = DateTime.ParseExact(splits[2], "yyyyMMddHHmmss", null).ToString("yyyy-MM-dd HH:mm:ss");
                        var image = Convert.ToBase64String(File.ReadAllBytes(files[i]));
                        var record = new FaceRecord(personSn, personName, createTime, image);

                        var json = JsonConvert.SerializeObject(record);

                        var url = _config.Url() + "/face/uploadFaceRecord?deviceSN=" + deviceSn;
                        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                        request.Method = WebRequestMethods.Http.Post;
                        request.MediaType = "application/json";

                        byte[] data = encoding.GetBytes(json);
                        using (Stream stream = request.GetRequestStream())
                        {
                            stream.Write(data, 0, data.Length);
                            stream.Flush();
                        }

                        _log.InfoFormat("上传识别记录成功:{0}", personSn);

                        File.Delete(files[i]);
                    }
                    catch (Exception ex)
                    {
                        _log.Error("上传识别记录异常", ex);
                    }
                    finally
                    {
                        Thread.Sleep(1500);
                    }
                }

            }
            catch (Exception ex)
            {
                _log.Error("上传识别记录异常", ex);
            }
        }

        private string GetMacAddressByNetworkInformation()
        {
            try
            {
                NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
                foreach (NetworkInterface ni in interfaces)
                {
                    return BitConverter.ToString(ni.GetPhysicalAddress().GetAddressBytes()).Replace("-","");
                }
            }
            catch (Exception)
            {
            }
            return "00-00-00-00-00-00";
        }

        public string HttpValidCard(string card)
        {
            try
            {
                var url = _config.ValidUrl() + "/face/validCard?deviceSN=" + deviceSn + "&card=" + card;
                string get = HttpHelper.Get(url);
                _log.InfoFormat("刷卡验证:{0}", get);
                JObject job = JObject.Parse(get);
                if (Convert.ToInt32(job["code"]) == 0)
                {
                    return Convert.ToString(job["msg"]);
                }
                return "";
            }
            catch (Exception ex)
            {
                _log.Error("刷卡验证异常", ex);
                return "";
            }
        }

        public string HttpValidCode(string code)
        {
            try
            {
                var url = _config.ValidUrl() + "/face/validCode?deviceSN=" + deviceSn + "&code=" + code;
                string get = HttpHelper.Get(url);
                _log.InfoFormat("刷卡验证:{0}", get);
                JObject job = JObject.Parse(get);
                if (Convert.ToInt32(job["code"]) == 0)
                {
                    return Convert.ToString(job["msg"]);
                }
                return "";
            }
            catch (Exception ex)
            {
                _log.Error("刷卡验证异常", ex);
                return "";
            }
        }
    }
}